/*
 * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder
 * Copyright (c) 2003-2010 Michael Niedermayer <michaelni@gmx.at>
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
 * @file
 * H.264 / AVC / MPEG4 part10 DSP functions.
 * @author Michael Niedermayer <michaelni@gmx.at>
 */

#include <stdint.h>
#include "avcodec.h"
#include "h264dsp.h"
#include "high_bit_depth.h"

#define BIT_DEPTH 8

#define op_scale1(x)  block[x] = av_clip_pixel( (block[x]*weight + offset) >> log2_denom )
#define op_scale2(x)  dst[x] = av_clip_pixel( (src[x]*weights + dst[x]*weightd + offset) >> (log2_denom+1))

static void weight_h264_pixels16x16_8_c(uint8_t *p_block, int stride, int log2_denom, int weight, int offset)
{
    int y;
    uint8_t *block = (uint8_t *)p_block;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (log2_denom + (8 - 8));
    if(log2_denom) offset += 1 << (log2_denom - 1);
    for(y = 0; y < 16; y++, block += stride)
    {
        block[0] = av_clip_uint8_c((block[0] * weight + offset) >> log2_denom);
        block[1] = av_clip_uint8_c((block[1] * weight + offset) >> log2_denom);
        if(16 == 2) continue;
        block[2] = av_clip_uint8_c((block[2] * weight + offset) >> log2_denom);
        block[3] = av_clip_uint8_c((block[3] * weight + offset) >> log2_denom);
        if(16 == 4) continue;
        block[4] = av_clip_uint8_c((block[4] * weight + offset) >> log2_denom);
        block[5] = av_clip_uint8_c((block[5] * weight + offset) >> log2_denom);
        block[6] = av_clip_uint8_c((block[6] * weight + offset) >> log2_denom);
        block[7] = av_clip_uint8_c((block[7] * weight + offset) >> log2_denom);
        if(16 == 8) continue;
        block[8] = av_clip_uint8_c((block[8] * weight + offset) >> log2_denom);
        block[9] = av_clip_uint8_c((block[9] * weight + offset) >> log2_denom);
        block[10] = av_clip_uint8_c((block[10] * weight + offset) >> log2_denom);
        block[11] = av_clip_uint8_c((block[11] * weight + offset) >> log2_denom);
        block[12] = av_clip_uint8_c((block[12] * weight + offset) >> log2_denom);
        block[13] = av_clip_uint8_c((block[13] * weight + offset) >> log2_denom);
        block[14] = av_clip_uint8_c((block[14] * weight + offset) >> log2_denom);
        block[15] = av_clip_uint8_c((block[15] * weight + offset) >> log2_denom);
    }
}
static void biweight_h264_pixels16x16_8_c(uint8_t *_dst, uint8_t *_src, int stride, int log2_denom, int weightd, int weights, int offset)
{
    int y;
    uint8_t *dst = (uint8_t *)_dst;
    uint8_t *src = (uint8_t *)_src;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (8 - 8);
    offset = ((offset + 1) | 1) << log2_denom;
    for(y = 0; y < 16; y++, dst += stride, src += stride)
    {
        dst[0] = av_clip_uint8_c((src[0] * weights + dst[0] * weightd + offset) >> (log2_denom + 1));
        dst[1] = av_clip_uint8_c((src[1] * weights + dst[1] * weightd + offset) >> (log2_denom + 1));
        if(16 == 2) continue;
        dst[2] = av_clip_uint8_c((src[2] * weights + dst[2] * weightd + offset) >> (log2_denom + 1));
        dst[3] = av_clip_uint8_c((src[3] * weights + dst[3] * weightd + offset) >> (log2_denom + 1));
        if(16 == 4) continue;
        dst[4] = av_clip_uint8_c((src[4] * weights + dst[4] * weightd + offset) >> (log2_denom + 1));
        dst[5] = av_clip_uint8_c((src[5] * weights + dst[5] * weightd + offset) >> (log2_denom + 1));
        dst[6] = av_clip_uint8_c((src[6] * weights + dst[6] * weightd + offset) >> (log2_denom + 1));
        dst[7] = av_clip_uint8_c((src[7] * weights + dst[7] * weightd + offset) >> (log2_denom + 1));
        if(16 == 8) continue;
        dst[8] = av_clip_uint8_c((src[8] * weights + dst[8] * weightd + offset) >> (log2_denom + 1));
        dst[9] = av_clip_uint8_c((src[9] * weights + dst[9] * weightd + offset) >> (log2_denom + 1));
        dst[10] = av_clip_uint8_c((src[10] * weights + dst[10] * weightd + offset) >> (log2_denom + 1));
        dst[11] = av_clip_uint8_c((src[11] * weights + dst[11] * weightd + offset) >> (log2_denom + 1));
        dst[12] = av_clip_uint8_c((src[12] * weights + dst[12] * weightd + offset) >> (log2_denom + 1));
        dst[13] = av_clip_uint8_c((src[13] * weights + dst[13] * weightd + offset) >> (log2_denom + 1));
        dst[14] = av_clip_uint8_c((src[14] * weights + dst[14] * weightd + offset) >> (log2_denom + 1));
        dst[15] = av_clip_uint8_c((src[15] * weights + dst[15] * weightd + offset) >> (log2_denom + 1));
    }
}
static void weight_h264_pixels16x8_8_c(uint8_t *p_block, int stride, int log2_denom, int weight, int offset)
{
    int y;
    uint8_t *block = (uint8_t *)p_block;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (log2_denom + (8 - 8));
    if(log2_denom) offset += 1 << (log2_denom - 1);
    for(y = 0; y < 8; y++, block += stride)
    {
        block[0] = av_clip_uint8_c((block[0] * weight + offset) >> log2_denom);
        block[1] = av_clip_uint8_c((block[1] * weight + offset) >> log2_denom);
        if(16 == 2) continue;
        block[2] = av_clip_uint8_c((block[2] * weight + offset) >> log2_denom);
        block[3] = av_clip_uint8_c((block[3] * weight + offset) >> log2_denom);
        if(16 == 4) continue;
        block[4] = av_clip_uint8_c((block[4] * weight + offset) >> log2_denom);
        block[5] = av_clip_uint8_c((block[5] * weight + offset) >> log2_denom);
        block[6] = av_clip_uint8_c((block[6] * weight + offset) >> log2_denom);
        block[7] = av_clip_uint8_c((block[7] * weight + offset) >> log2_denom);
        if(16 == 8) continue;
        block[8] = av_clip_uint8_c((block[8] * weight + offset) >> log2_denom);
        block[9] = av_clip_uint8_c((block[9] * weight + offset) >> log2_denom);
        block[10] = av_clip_uint8_c((block[10] * weight + offset) >> log2_denom);
        block[11] = av_clip_uint8_c((block[11] * weight + offset) >> log2_denom);
        block[12] = av_clip_uint8_c((block[12] * weight + offset) >> log2_denom);
        block[13] = av_clip_uint8_c((block[13] * weight + offset) >> log2_denom);
        block[14] = av_clip_uint8_c((block[14] * weight + offset) >> log2_denom);
        block[15] = av_clip_uint8_c((block[15] * weight + offset) >> log2_denom);
    }
}
static void biweight_h264_pixels16x8_8_c(uint8_t *_dst, uint8_t *_src, int stride, int log2_denom, int weightd, int weights, int offset)
{
    int y;
    uint8_t *dst = (uint8_t *)_dst;
    uint8_t *src = (uint8_t *)_src;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (8 - 8);
    offset = ((offset + 1) | 1) << log2_denom;
    for(y = 0; y < 8; y++, dst += stride, src += stride)
    {
        dst[0] = av_clip_uint8_c((src[0] * weights + dst[0] * weightd + offset) >> (log2_denom + 1));
        dst[1] = av_clip_uint8_c((src[1] * weights + dst[1] * weightd + offset) >> (log2_denom + 1));
        if(16 == 2) continue;
        dst[2] = av_clip_uint8_c((src[2] * weights + dst[2] * weightd + offset) >> (log2_denom + 1));
        dst[3] = av_clip_uint8_c((src[3] * weights + dst[3] * weightd + offset) >> (log2_denom + 1));
        if(16 == 4) continue;
        dst[4] = av_clip_uint8_c((src[4] * weights + dst[4] * weightd + offset) >> (log2_denom + 1));
        dst[5] = av_clip_uint8_c((src[5] * weights + dst[5] * weightd + offset) >> (log2_denom + 1));
        dst[6] = av_clip_uint8_c((src[6] * weights + dst[6] * weightd + offset) >> (log2_denom + 1));
        dst[7] = av_clip_uint8_c((src[7] * weights + dst[7] * weightd + offset) >> (log2_denom + 1));
        if(16 == 8) continue;
        dst[8] = av_clip_uint8_c((src[8] * weights + dst[8] * weightd + offset) >> (log2_denom + 1));
        dst[9] = av_clip_uint8_c((src[9] * weights + dst[9] * weightd + offset) >> (log2_denom + 1));
        dst[10] = av_clip_uint8_c((src[10] * weights + dst[10] * weightd + offset) >> (log2_denom + 1));
        dst[11] = av_clip_uint8_c((src[11] * weights + dst[11] * weightd + offset) >> (log2_denom + 1));
        dst[12] = av_clip_uint8_c((src[12] * weights + dst[12] * weightd + offset) >> (log2_denom + 1));
        dst[13] = av_clip_uint8_c((src[13] * weights + dst[13] * weightd + offset) >> (log2_denom + 1));
        dst[14] = av_clip_uint8_c((src[14] * weights + dst[14] * weightd + offset) >> (log2_denom + 1));
        dst[15] = av_clip_uint8_c((src[15] * weights + dst[15] * weightd + offset) >> (log2_denom + 1));
    }
}
static void weight_h264_pixels8x16_8_c(uint8_t *p_block, int stride, int log2_denom, int weight, int offset)
{
    int y;
    uint8_t *block = (uint8_t *)p_block;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (log2_denom + (8 - 8));
    if(log2_denom) offset += 1 << (log2_denom - 1);
    for(y = 0; y < 16; y++, block += stride)
    {
        block[0] = av_clip_uint8_c((block[0] * weight + offset) >> log2_denom);
        block[1] = av_clip_uint8_c((block[1] * weight + offset) >> log2_denom);
        if(8 == 2) continue;
        block[2] = av_clip_uint8_c((block[2] * weight + offset) >> log2_denom);
        block[3] = av_clip_uint8_c((block[3] * weight + offset) >> log2_denom);
        if(8 == 4) continue;
        block[4] = av_clip_uint8_c((block[4] * weight + offset) >> log2_denom);
        block[5] = av_clip_uint8_c((block[5] * weight + offset) >> log2_denom);
        block[6] = av_clip_uint8_c((block[6] * weight + offset) >> log2_denom);
        block[7] = av_clip_uint8_c((block[7] * weight + offset) >> log2_denom);
        if(8 == 8) continue;
        block[8] = av_clip_uint8_c((block[8] * weight + offset) >> log2_denom);
        block[9] = av_clip_uint8_c((block[9] * weight + offset) >> log2_denom);
        block[10] = av_clip_uint8_c((block[10] * weight + offset) >> log2_denom);
        block[11] = av_clip_uint8_c((block[11] * weight + offset) >> log2_denom);
        block[12] = av_clip_uint8_c((block[12] * weight + offset) >> log2_denom);
        block[13] = av_clip_uint8_c((block[13] * weight + offset) >> log2_denom);
        block[14] = av_clip_uint8_c((block[14] * weight + offset) >> log2_denom);
        block[15] = av_clip_uint8_c((block[15] * weight + offset) >> log2_denom);
    }
}
static void biweight_h264_pixels8x16_8_c(uint8_t *_dst, uint8_t *_src, int stride, int log2_denom, int weightd, int weights, int offset)
{
    int y;
    uint8_t *dst = (uint8_t *)_dst;
    uint8_t *src = (uint8_t *)_src;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (8 - 8);
    offset = ((offset + 1) | 1) << log2_denom;
    for(y = 0; y < 16; y++, dst += stride, src += stride)
    {
        dst[0] = av_clip_uint8_c((src[0] * weights + dst[0] * weightd + offset) >> (log2_denom + 1));
        dst[1] = av_clip_uint8_c((src[1] * weights + dst[1] * weightd + offset) >> (log2_denom + 1));
        if(8 == 2) continue;
        dst[2] = av_clip_uint8_c((src[2] * weights + dst[2] * weightd + offset) >> (log2_denom + 1));
        dst[3] = av_clip_uint8_c((src[3] * weights + dst[3] * weightd + offset) >> (log2_denom + 1));
        if(8 == 4) continue;
        dst[4] = av_clip_uint8_c((src[4] * weights + dst[4] * weightd + offset) >> (log2_denom + 1));
        dst[5] = av_clip_uint8_c((src[5] * weights + dst[5] * weightd + offset) >> (log2_denom + 1));
        dst[6] = av_clip_uint8_c((src[6] * weights + dst[6] * weightd + offset) >> (log2_denom + 1));
        dst[7] = av_clip_uint8_c((src[7] * weights + dst[7] * weightd + offset) >> (log2_denom + 1));
        if(8 == 8) continue;
        dst[8] = av_clip_uint8_c((src[8] * weights + dst[8] * weightd + offset) >> (log2_denom + 1));
        dst[9] = av_clip_uint8_c((src[9] * weights + dst[9] * weightd + offset) >> (log2_denom + 1));
        dst[10] = av_clip_uint8_c((src[10] * weights + dst[10] * weightd + offset) >> (log2_denom + 1));
        dst[11] = av_clip_uint8_c((src[11] * weights + dst[11] * weightd + offset) >> (log2_denom + 1));
        dst[12] = av_clip_uint8_c((src[12] * weights + dst[12] * weightd + offset) >> (log2_denom + 1));
        dst[13] = av_clip_uint8_c((src[13] * weights + dst[13] * weightd + offset) >> (log2_denom + 1));
        dst[14] = av_clip_uint8_c((src[14] * weights + dst[14] * weightd + offset) >> (log2_denom + 1));
        dst[15] = av_clip_uint8_c((src[15] * weights + dst[15] * weightd + offset) >> (log2_denom + 1));
    }
}
static void weight_h264_pixels8x8_8_c(uint8_t *p_block, int stride, int log2_denom, int weight, int offset)
{
    int y;
    uint8_t *block = (uint8_t *)p_block;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (log2_denom + (8 - 8));
    if(log2_denom) offset += 1 << (log2_denom - 1);
    for(y = 0; y < 8; y++, block += stride)
    {
        block[0] = av_clip_uint8_c((block[0] * weight + offset) >> log2_denom);
        block[1] = av_clip_uint8_c((block[1] * weight + offset) >> log2_denom);
        if(8 == 2) continue;
        block[2] = av_clip_uint8_c((block[2] * weight + offset) >> log2_denom);
        block[3] = av_clip_uint8_c((block[3] * weight + offset) >> log2_denom);
        if(8 == 4) continue;
        block[4] = av_clip_uint8_c((block[4] * weight + offset) >> log2_denom);
        block[5] = av_clip_uint8_c((block[5] * weight + offset) >> log2_denom);
        block[6] = av_clip_uint8_c((block[6] * weight + offset) >> log2_denom);
        block[7] = av_clip_uint8_c((block[7] * weight + offset) >> log2_denom);
        if(8 == 8) continue;
        block[8] = av_clip_uint8_c((block[8] * weight + offset) >> log2_denom);
        block[9] = av_clip_uint8_c((block[9] * weight + offset) >> log2_denom);
        block[10] = av_clip_uint8_c((block[10] * weight + offset) >> log2_denom);
        block[11] = av_clip_uint8_c((block[11] * weight + offset) >> log2_denom);
        block[12] = av_clip_uint8_c((block[12] * weight + offset) >> log2_denom);
        block[13] = av_clip_uint8_c((block[13] * weight + offset) >> log2_denom);
        block[14] = av_clip_uint8_c((block[14] * weight + offset) >> log2_denom);
        block[15] = av_clip_uint8_c((block[15] * weight + offset) >> log2_denom);
    }
}
static void biweight_h264_pixels8x8_8_c(uint8_t *_dst, uint8_t *_src, int stride, int log2_denom, int weightd, int weights, int offset)
{
    int y;
    uint8_t *dst = (uint8_t *)_dst;
    uint8_t *src = (uint8_t *)_src;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (8 - 8);
    offset = ((offset + 1) | 1) << log2_denom;
    for(y = 0; y < 8; y++, dst += stride, src += stride)
    {
        dst[0] = av_clip_uint8_c((src[0] * weights + dst[0] * weightd + offset) >> (log2_denom + 1));
        dst[1] = av_clip_uint8_c((src[1] * weights + dst[1] * weightd + offset) >> (log2_denom + 1));
        if(8 == 2) continue;
        dst[2] = av_clip_uint8_c((src[2] * weights + dst[2] * weightd + offset) >> (log2_denom + 1));
        dst[3] = av_clip_uint8_c((src[3] * weights + dst[3] * weightd + offset) >> (log2_denom + 1));
        if(8 == 4) continue;
        dst[4] = av_clip_uint8_c((src[4] * weights + dst[4] * weightd + offset) >> (log2_denom + 1));
        dst[5] = av_clip_uint8_c((src[5] * weights + dst[5] * weightd + offset) >> (log2_denom + 1));
        dst[6] = av_clip_uint8_c((src[6] * weights + dst[6] * weightd + offset) >> (log2_denom + 1));
        dst[7] = av_clip_uint8_c((src[7] * weights + dst[7] * weightd + offset) >> (log2_denom + 1));
        if(8 == 8) continue;
        dst[8] = av_clip_uint8_c((src[8] * weights + dst[8] * weightd + offset) >> (log2_denom + 1));
        dst[9] = av_clip_uint8_c((src[9] * weights + dst[9] * weightd + offset) >> (log2_denom + 1));
        dst[10] = av_clip_uint8_c((src[10] * weights + dst[10] * weightd + offset) >> (log2_denom + 1));
        dst[11] = av_clip_uint8_c((src[11] * weights + dst[11] * weightd + offset) >> (log2_denom + 1));
        dst[12] = av_clip_uint8_c((src[12] * weights + dst[12] * weightd + offset) >> (log2_denom + 1));
        dst[13] = av_clip_uint8_c((src[13] * weights + dst[13] * weightd + offset) >> (log2_denom + 1));
        dst[14] = av_clip_uint8_c((src[14] * weights + dst[14] * weightd + offset) >> (log2_denom + 1));
        dst[15] = av_clip_uint8_c((src[15] * weights + dst[15] * weightd + offset) >> (log2_denom + 1));
    }
}
static void weight_h264_pixels8x4_8_c(uint8_t *p_block, int stride, int log2_denom, int weight, int offset)
{
    int y;
    uint8_t *block = (uint8_t *)p_block;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (log2_denom + (8 - 8));
    if(log2_denom) offset += 1 << (log2_denom - 1);
    for(y = 0; y < 4; y++, block += stride)
    {
        block[0] = av_clip_uint8_c((block[0] * weight + offset) >> log2_denom);
        block[1] = av_clip_uint8_c((block[1] * weight + offset) >> log2_denom);
        if(8 == 2) continue;
        block[2] = av_clip_uint8_c((block[2] * weight + offset) >> log2_denom);
        block[3] = av_clip_uint8_c((block[3] * weight + offset) >> log2_denom);
        if(8 == 4) continue;
        block[4] = av_clip_uint8_c((block[4] * weight + offset) >> log2_denom);
        block[5] = av_clip_uint8_c((block[5] * weight + offset) >> log2_denom);
        block[6] = av_clip_uint8_c((block[6] * weight + offset) >> log2_denom);
        block[7] = av_clip_uint8_c((block[7] * weight + offset) >> log2_denom);
        if(8 == 8) continue;
        block[8] = av_clip_uint8_c((block[8] * weight + offset) >> log2_denom);
        block[9] = av_clip_uint8_c((block[9] * weight + offset) >> log2_denom);
        block[10] = av_clip_uint8_c((block[10] * weight + offset) >> log2_denom);
        block[11] = av_clip_uint8_c((block[11] * weight + offset) >> log2_denom);
        block[12] = av_clip_uint8_c((block[12] * weight + offset) >> log2_denom);
        block[13] = av_clip_uint8_c((block[13] * weight + offset) >> log2_denom);
        block[14] = av_clip_uint8_c((block[14] * weight + offset) >> log2_denom);
        block[15] = av_clip_uint8_c((block[15] * weight + offset) >> log2_denom);
    }
}
static void biweight_h264_pixels8x4_8_c(uint8_t *_dst, uint8_t *_src, int stride, int log2_denom, int weightd, int weights, int offset)
{
    int y;
    uint8_t *dst = (uint8_t *)_dst;
    uint8_t *src = (uint8_t *)_src;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (8 - 8);
    offset = ((offset + 1) | 1) << log2_denom;
    for(y = 0; y < 4; y++, dst += stride, src += stride)
    {
        dst[0] = av_clip_uint8_c((src[0] * weights + dst[0] * weightd + offset) >> (log2_denom + 1));
        dst[1] = av_clip_uint8_c((src[1] * weights + dst[1] * weightd + offset) >> (log2_denom + 1));
        if(8 == 2) continue;
        dst[2] = av_clip_uint8_c((src[2] * weights + dst[2] * weightd + offset) >> (log2_denom + 1));
        dst[3] = av_clip_uint8_c((src[3] * weights + dst[3] * weightd + offset) >> (log2_denom + 1));
        if(8 == 4) continue;
        dst[4] = av_clip_uint8_c((src[4] * weights + dst[4] * weightd + offset) >> (log2_denom + 1));
        dst[5] = av_clip_uint8_c((src[5] * weights + dst[5] * weightd + offset) >> (log2_denom + 1));
        dst[6] = av_clip_uint8_c((src[6] * weights + dst[6] * weightd + offset) >> (log2_denom + 1));
        dst[7] = av_clip_uint8_c((src[7] * weights + dst[7] * weightd + offset) >> (log2_denom + 1));
        if(8 == 8) continue;
        dst[8] = av_clip_uint8_c((src[8] * weights + dst[8] * weightd + offset) >> (log2_denom + 1));
        dst[9] = av_clip_uint8_c((src[9] * weights + dst[9] * weightd + offset) >> (log2_denom + 1));
        dst[10] = av_clip_uint8_c((src[10] * weights + dst[10] * weightd + offset) >> (log2_denom + 1));
        dst[11] = av_clip_uint8_c((src[11] * weights + dst[11] * weightd + offset) >> (log2_denom + 1));
        dst[12] = av_clip_uint8_c((src[12] * weights + dst[12] * weightd + offset) >> (log2_denom + 1));
        dst[13] = av_clip_uint8_c((src[13] * weights + dst[13] * weightd + offset) >> (log2_denom + 1));
        dst[14] = av_clip_uint8_c((src[14] * weights + dst[14] * weightd + offset) >> (log2_denom + 1));
        dst[15] = av_clip_uint8_c((src[15] * weights + dst[15] * weightd + offset) >> (log2_denom + 1));
    }
}
static void weight_h264_pixels4x8_8_c(uint8_t *p_block, int stride, int log2_denom, int weight, int offset)
{
    int y;
    uint8_t *block = (uint8_t *)p_block;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (log2_denom + (8 - 8));
    if(log2_denom) offset += 1 << (log2_denom - 1);
    for(y = 0; y < 8; y++, block += stride)
    {
        block[0] = av_clip_uint8_c((block[0] * weight + offset) >> log2_denom);
        block[1] = av_clip_uint8_c((block[1] * weight + offset) >> log2_denom);
        if(4 == 2) continue;
        block[2] = av_clip_uint8_c((block[2] * weight + offset) >> log2_denom);
        block[3] = av_clip_uint8_c((block[3] * weight + offset) >> log2_denom);
        if(4 == 4) continue;
        block[4] = av_clip_uint8_c((block[4] * weight + offset) >> log2_denom);
        block[5] = av_clip_uint8_c((block[5] * weight + offset) >> log2_denom);
        block[6] = av_clip_uint8_c((block[6] * weight + offset) >> log2_denom);
        block[7] = av_clip_uint8_c((block[7] * weight + offset) >> log2_denom);
        if(4 == 8) continue;
        block[8] = av_clip_uint8_c((block[8] * weight + offset) >> log2_denom);
        block[9] = av_clip_uint8_c((block[9] * weight + offset) >> log2_denom);
        block[10] = av_clip_uint8_c((block[10] * weight + offset) >> log2_denom);
        block[11] = av_clip_uint8_c((block[11] * weight + offset) >> log2_denom);
        block[12] = av_clip_uint8_c((block[12] * weight + offset) >> log2_denom);
        block[13] = av_clip_uint8_c((block[13] * weight + offset) >> log2_denom);
        block[14] = av_clip_uint8_c((block[14] * weight + offset) >> log2_denom);
        block[15] = av_clip_uint8_c((block[15] * weight + offset) >> log2_denom);
    }
}
static void biweight_h264_pixels4x8_8_c(uint8_t *_dst, uint8_t *_src, int stride, int log2_denom, int weightd, int weights, int offset)
{
    int y;
    uint8_t *dst = (uint8_t *)_dst;
    uint8_t *src = (uint8_t *)_src;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (8 - 8);
    offset = ((offset + 1) | 1) << log2_denom;
    for(y = 0; y < 8; y++, dst += stride, src += stride)
    {
        dst[0] = av_clip_uint8_c((src[0] * weights + dst[0] * weightd + offset) >> (log2_denom + 1));
        dst[1] = av_clip_uint8_c((src[1] * weights + dst[1] * weightd + offset) >> (log2_denom + 1));
        if(4 == 2) continue;
        dst[2] = av_clip_uint8_c((src[2] * weights + dst[2] * weightd + offset) >> (log2_denom + 1));
        dst[3] = av_clip_uint8_c((src[3] * weights + dst[3] * weightd + offset) >> (log2_denom + 1));
        if(4 == 4) continue;
        dst[4] = av_clip_uint8_c((src[4] * weights + dst[4] * weightd + offset) >> (log2_denom + 1));
        dst[5] = av_clip_uint8_c((src[5] * weights + dst[5] * weightd + offset) >> (log2_denom + 1));
        dst[6] = av_clip_uint8_c((src[6] * weights + dst[6] * weightd + offset) >> (log2_denom + 1));
        dst[7] = av_clip_uint8_c((src[7] * weights + dst[7] * weightd + offset) >> (log2_denom + 1));
        if(4 == 8) continue;
        dst[8] = av_clip_uint8_c((src[8] * weights + dst[8] * weightd + offset) >> (log2_denom + 1));
        dst[9] = av_clip_uint8_c((src[9] * weights + dst[9] * weightd + offset) >> (log2_denom + 1));
        dst[10] = av_clip_uint8_c((src[10] * weights + dst[10] * weightd + offset) >> (log2_denom + 1));
        dst[11] = av_clip_uint8_c((src[11] * weights + dst[11] * weightd + offset) >> (log2_denom + 1));
        dst[12] = av_clip_uint8_c((src[12] * weights + dst[12] * weightd + offset) >> (log2_denom + 1));
        dst[13] = av_clip_uint8_c((src[13] * weights + dst[13] * weightd + offset) >> (log2_denom + 1));
        dst[14] = av_clip_uint8_c((src[14] * weights + dst[14] * weightd + offset) >> (log2_denom + 1));
        dst[15] = av_clip_uint8_c((src[15] * weights + dst[15] * weightd + offset) >> (log2_denom + 1));
    }
}
static void weight_h264_pixels4x4_8_c(uint8_t *p_block, int stride, int log2_denom, int weight, int offset)
{
    int y;
    uint8_t *block = (uint8_t *)p_block;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (log2_denom + (8 - 8));
    if(log2_denom) offset += 1 << (log2_denom - 1);
    for(y = 0; y < 4; y++, block += stride)
    {
        block[0] = av_clip_uint8_c((block[0] * weight + offset) >> log2_denom);
        block[1] = av_clip_uint8_c((block[1] * weight + offset) >> log2_denom);
        if(4 == 2) continue;
        block[2] = av_clip_uint8_c((block[2] * weight + offset) >> log2_denom);
        block[3] = av_clip_uint8_c((block[3] * weight + offset) >> log2_denom);
        if(4 == 4) continue;
        block[4] = av_clip_uint8_c((block[4] * weight + offset) >> log2_denom);
        block[5] = av_clip_uint8_c((block[5] * weight + offset) >> log2_denom);
        block[6] = av_clip_uint8_c((block[6] * weight + offset) >> log2_denom);
        block[7] = av_clip_uint8_c((block[7] * weight + offset) >> log2_denom);
        if(4 == 8) continue;
        block[8] = av_clip_uint8_c((block[8] * weight + offset) >> log2_denom);
        block[9] = av_clip_uint8_c((block[9] * weight + offset) >> log2_denom);
        block[10] = av_clip_uint8_c((block[10] * weight + offset) >> log2_denom);
        block[11] = av_clip_uint8_c((block[11] * weight + offset) >> log2_denom);
        block[12] = av_clip_uint8_c((block[12] * weight + offset) >> log2_denom);
        block[13] = av_clip_uint8_c((block[13] * weight + offset) >> log2_denom);
        block[14] = av_clip_uint8_c((block[14] * weight + offset) >> log2_denom);
        block[15] = av_clip_uint8_c((block[15] * weight + offset) >> log2_denom);
    }
}
static void biweight_h264_pixels4x4_8_c(uint8_t *_dst, uint8_t *_src, int stride, int log2_denom, int weightd, int weights, int offset)
{
    int y;
    uint8_t *dst = (uint8_t *)_dst;
    uint8_t *src = (uint8_t *)_src;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (8 - 8);
    offset = ((offset + 1) | 1) << log2_denom;
    for(y = 0; y < 4; y++, dst += stride, src += stride)
    {
        dst[0] = av_clip_uint8_c((src[0] * weights + dst[0] * weightd + offset) >> (log2_denom + 1));
        dst[1] = av_clip_uint8_c((src[1] * weights + dst[1] * weightd + offset) >> (log2_denom + 1));
        if(4 == 2) continue;
        dst[2] = av_clip_uint8_c((src[2] * weights + dst[2] * weightd + offset) >> (log2_denom + 1));
        dst[3] = av_clip_uint8_c((src[3] * weights + dst[3] * weightd + offset) >> (log2_denom + 1));
        if(4 == 4) continue;
        dst[4] = av_clip_uint8_c((src[4] * weights + dst[4] * weightd + offset) >> (log2_denom + 1));
        dst[5] = av_clip_uint8_c((src[5] * weights + dst[5] * weightd + offset) >> (log2_denom + 1));
        dst[6] = av_clip_uint8_c((src[6] * weights + dst[6] * weightd + offset) >> (log2_denom + 1));
        dst[7] = av_clip_uint8_c((src[7] * weights + dst[7] * weightd + offset) >> (log2_denom + 1));
        if(4 == 8) continue;
        dst[8] = av_clip_uint8_c((src[8] * weights + dst[8] * weightd + offset) >> (log2_denom + 1));
        dst[9] = av_clip_uint8_c((src[9] * weights + dst[9] * weightd + offset) >> (log2_denom + 1));
        dst[10] = av_clip_uint8_c((src[10] * weights + dst[10] * weightd + offset) >> (log2_denom + 1));
        dst[11] = av_clip_uint8_c((src[11] * weights + dst[11] * weightd + offset) >> (log2_denom + 1));
        dst[12] = av_clip_uint8_c((src[12] * weights + dst[12] * weightd + offset) >> (log2_denom + 1));
        dst[13] = av_clip_uint8_c((src[13] * weights + dst[13] * weightd + offset) >> (log2_denom + 1));
        dst[14] = av_clip_uint8_c((src[14] * weights + dst[14] * weightd + offset) >> (log2_denom + 1));
        dst[15] = av_clip_uint8_c((src[15] * weights + dst[15] * weightd + offset) >> (log2_denom + 1));
    }
}
static void weight_h264_pixels4x2_8_c(uint8_t *p_block, int stride, int log2_denom, int weight, int offset)
{
    int y;
    uint8_t *block = (uint8_t *)p_block;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (log2_denom + (8 - 8));
    if(log2_denom) offset += 1 << (log2_denom - 1);
    for(y = 0; y < 2; y++, block += stride)
    {
        block[0] = av_clip_uint8_c((block[0] * weight + offset) >> log2_denom);
        block[1] = av_clip_uint8_c((block[1] * weight + offset) >> log2_denom);
        if(4 == 2) continue;
        block[2] = av_clip_uint8_c((block[2] * weight + offset) >> log2_denom);
        block[3] = av_clip_uint8_c((block[3] * weight + offset) >> log2_denom);
        if(4 == 4) continue;
        block[4] = av_clip_uint8_c((block[4] * weight + offset) >> log2_denom);
        block[5] = av_clip_uint8_c((block[5] * weight + offset) >> log2_denom);
        block[6] = av_clip_uint8_c((block[6] * weight + offset) >> log2_denom);
        block[7] = av_clip_uint8_c((block[7] * weight + offset) >> log2_denom);
        if(4 == 8) continue;
        block[8] = av_clip_uint8_c((block[8] * weight + offset) >> log2_denom);
        block[9] = av_clip_uint8_c((block[9] * weight + offset) >> log2_denom);
        block[10] = av_clip_uint8_c((block[10] * weight + offset) >> log2_denom);
        block[11] = av_clip_uint8_c((block[11] * weight + offset) >> log2_denom);
        block[12] = av_clip_uint8_c((block[12] * weight + offset) >> log2_denom);
        block[13] = av_clip_uint8_c((block[13] * weight + offset) >> log2_denom);
        block[14] = av_clip_uint8_c((block[14] * weight + offset) >> log2_denom);
        block[15] = av_clip_uint8_c((block[15] * weight + offset) >> log2_denom);
    }
}
static void biweight_h264_pixels4x2_8_c(uint8_t *_dst, uint8_t *_src, int stride, int log2_denom, int weightd, int weights, int offset)
{
    int y;
    uint8_t *dst = (uint8_t *)_dst;
    uint8_t *src = (uint8_t *)_src;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (8 - 8);
    offset = ((offset + 1) | 1) << log2_denom;
    for(y = 0; y < 2; y++, dst += stride, src += stride)
    {
        dst[0] = av_clip_uint8_c((src[0] * weights + dst[0] * weightd + offset) >> (log2_denom + 1));
        dst[1] = av_clip_uint8_c((src[1] * weights + dst[1] * weightd + offset) >> (log2_denom + 1));
        if(4 == 2) continue;
        dst[2] = av_clip_uint8_c((src[2] * weights + dst[2] * weightd + offset) >> (log2_denom + 1));
        dst[3] = av_clip_uint8_c((src[3] * weights + dst[3] * weightd + offset) >> (log2_denom + 1));
        if(4 == 4) continue;
        dst[4] = av_clip_uint8_c((src[4] * weights + dst[4] * weightd + offset) >> (log2_denom + 1));
        dst[5] = av_clip_uint8_c((src[5] * weights + dst[5] * weightd + offset) >> (log2_denom + 1));
        dst[6] = av_clip_uint8_c((src[6] * weights + dst[6] * weightd + offset) >> (log2_denom + 1));
        dst[7] = av_clip_uint8_c((src[7] * weights + dst[7] * weightd + offset) >> (log2_denom + 1));
        if(4 == 8) continue;
        dst[8] = av_clip_uint8_c((src[8] * weights + dst[8] * weightd + offset) >> (log2_denom + 1));
        dst[9] = av_clip_uint8_c((src[9] * weights + dst[9] * weightd + offset) >> (log2_denom + 1));
        dst[10] = av_clip_uint8_c((src[10] * weights + dst[10] * weightd + offset) >> (log2_denom + 1));
        dst[11] = av_clip_uint8_c((src[11] * weights + dst[11] * weightd + offset) >> (log2_denom + 1));
        dst[12] = av_clip_uint8_c((src[12] * weights + dst[12] * weightd + offset) >> (log2_denom + 1));
        dst[13] = av_clip_uint8_c((src[13] * weights + dst[13] * weightd + offset) >> (log2_denom + 1));
        dst[14] = av_clip_uint8_c((src[14] * weights + dst[14] * weightd + offset) >> (log2_denom + 1));
        dst[15] = av_clip_uint8_c((src[15] * weights + dst[15] * weightd + offset) >> (log2_denom + 1));
    }
}
static void weight_h264_pixels2x4_8_c(uint8_t *p_block, int stride, int log2_denom, int weight, int offset)
{
    int y;
    uint8_t *block = (uint8_t *)p_block;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (log2_denom + (8 - 8));
    if(log2_denom) offset += 1 << (log2_denom - 1);
    for(y = 0; y < 4; y++, block += stride)
    {
        block[0] = av_clip_uint8_c((block[0] * weight + offset) >> log2_denom);
        block[1] = av_clip_uint8_c((block[1] * weight + offset) >> log2_denom);
        if(2 == 2) continue;
        block[2] = av_clip_uint8_c((block[2] * weight + offset) >> log2_denom);
        block[3] = av_clip_uint8_c((block[3] * weight + offset) >> log2_denom);
        if(2 == 4) continue;
        block[4] = av_clip_uint8_c((block[4] * weight + offset) >> log2_denom);
        block[5] = av_clip_uint8_c((block[5] * weight + offset) >> log2_denom);
        block[6] = av_clip_uint8_c((block[6] * weight + offset) >> log2_denom);
        block[7] = av_clip_uint8_c((block[7] * weight + offset) >> log2_denom);
        if(2 == 8) continue;
        block[8] = av_clip_uint8_c((block[8] * weight + offset) >> log2_denom);
        block[9] = av_clip_uint8_c((block[9] * weight + offset) >> log2_denom);
        block[10] = av_clip_uint8_c((block[10] * weight + offset) >> log2_denom);
        block[11] = av_clip_uint8_c((block[11] * weight + offset) >> log2_denom);
        block[12] = av_clip_uint8_c((block[12] * weight + offset) >> log2_denom);
        block[13] = av_clip_uint8_c((block[13] * weight + offset) >> log2_denom);
        block[14] = av_clip_uint8_c((block[14] * weight + offset) >> log2_denom);
        block[15] = av_clip_uint8_c((block[15] * weight + offset) >> log2_denom);
    }
}
static void biweight_h264_pixels2x4_8_c(uint8_t *_dst, uint8_t *_src, int stride, int log2_denom, int weightd, int weights, int offset)
{
    int y;
    uint8_t *dst = (uint8_t *)_dst;
    uint8_t *src = (uint8_t *)_src;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (8 - 8);
    offset = ((offset + 1) | 1) << log2_denom;
    for(y = 0; y < 4; y++, dst += stride, src += stride)
    {
        dst[0] = av_clip_uint8_c((src[0] * weights + dst[0] * weightd + offset) >> (log2_denom + 1));
        dst[1] = av_clip_uint8_c((src[1] * weights + dst[1] * weightd + offset) >> (log2_denom + 1));
        if(2 == 2) continue;
        dst[2] = av_clip_uint8_c((src[2] * weights + dst[2] * weightd + offset) >> (log2_denom + 1));
        dst[3] = av_clip_uint8_c((src[3] * weights + dst[3] * weightd + offset) >> (log2_denom + 1));
        if(2 == 4) continue;
        dst[4] = av_clip_uint8_c((src[4] * weights + dst[4] * weightd + offset) >> (log2_denom + 1));
        dst[5] = av_clip_uint8_c((src[5] * weights + dst[5] * weightd + offset) >> (log2_denom + 1));
        dst[6] = av_clip_uint8_c((src[6] * weights + dst[6] * weightd + offset) >> (log2_denom + 1));
        dst[7] = av_clip_uint8_c((src[7] * weights + dst[7] * weightd + offset) >> (log2_denom + 1));
        if(2 == 8) continue;
        dst[8] = av_clip_uint8_c((src[8] * weights + dst[8] * weightd + offset) >> (log2_denom + 1));
        dst[9] = av_clip_uint8_c((src[9] * weights + dst[9] * weightd + offset) >> (log2_denom + 1));
        dst[10] = av_clip_uint8_c((src[10] * weights + dst[10] * weightd + offset) >> (log2_denom + 1));
        dst[11] = av_clip_uint8_c((src[11] * weights + dst[11] * weightd + offset) >> (log2_denom + 1));
        dst[12] = av_clip_uint8_c((src[12] * weights + dst[12] * weightd + offset) >> (log2_denom + 1));
        dst[13] = av_clip_uint8_c((src[13] * weights + dst[13] * weightd + offset) >> (log2_denom + 1));
        dst[14] = av_clip_uint8_c((src[14] * weights + dst[14] * weightd + offset) >> (log2_denom + 1));
        dst[15] = av_clip_uint8_c((src[15] * weights + dst[15] * weightd + offset) >> (log2_denom + 1));
    }
}
static void weight_h264_pixels2x2_8_c(uint8_t *p_block, int stride, int log2_denom, int weight, int offset)
{
    int y;
    uint8_t *block = (uint8_t *)p_block;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (log2_denom + (8 - 8));
    if(log2_denom) offset += 1 << (log2_denom - 1);
    for(y = 0; y < 2; y++, block += stride)
    {
        block[0] = av_clip_uint8_c((block[0] * weight + offset) >> log2_denom);
        block[1] = av_clip_uint8_c((block[1] * weight + offset) >> log2_denom);
        if(2 == 2) continue;
        block[2] = av_clip_uint8_c((block[2] * weight + offset) >> log2_denom);
        block[3] = av_clip_uint8_c((block[3] * weight + offset) >> log2_denom);
        if(2 == 4) continue;
        block[4] = av_clip_uint8_c((block[4] * weight + offset) >> log2_denom);
        block[5] = av_clip_uint8_c((block[5] * weight + offset) >> log2_denom);
        block[6] = av_clip_uint8_c((block[6] * weight + offset) >> log2_denom);
        block[7] = av_clip_uint8_c((block[7] * weight + offset) >> log2_denom);
        if(2 == 8) continue;
        block[8] = av_clip_uint8_c((block[8] * weight + offset) >> log2_denom);
        block[9] = av_clip_uint8_c((block[9] * weight + offset) >> log2_denom);
        block[10] = av_clip_uint8_c((block[10] * weight + offset) >> log2_denom);
        block[11] = av_clip_uint8_c((block[11] * weight + offset) >> log2_denom);
        block[12] = av_clip_uint8_c((block[12] * weight + offset) >> log2_denom);
        block[13] = av_clip_uint8_c((block[13] * weight + offset) >> log2_denom);
        block[14] = av_clip_uint8_c((block[14] * weight + offset) >> log2_denom);
        block[15] = av_clip_uint8_c((block[15] * weight + offset) >> log2_denom);
    }
}
static void biweight_h264_pixels2x2_8_c(uint8_t *_dst, uint8_t *_src, int stride, int log2_denom, int weightd, int weights, int offset)
{
    int y;
    uint8_t *dst = (uint8_t *)_dst;
    uint8_t *src = (uint8_t *)_src;
    stride >>= sizeof(uint8_t) - 1;
    offset <<= (8 - 8);
    offset = ((offset + 1) | 1) << log2_denom;
    for(y = 0; y < 2; y++, dst += stride, src += stride)
    {
        dst[0] = av_clip_uint8_c((src[0] * weights + dst[0] * weightd + offset) >> (log2_denom + 1));
        dst[1] = av_clip_uint8_c((src[1] * weights + dst[1] * weightd + offset) >> (log2_denom + 1));
        if(2 == 2) continue;
        dst[2] = av_clip_uint8_c((src[2] * weights + dst[2] * weightd + offset) >> (log2_denom + 1));
        dst[3] = av_clip_uint8_c((src[3] * weights + dst[3] * weightd + offset) >> (log2_denom + 1));
        if(2 == 4) continue;
        dst[4] = av_clip_uint8_c((src[4] * weights + dst[4] * weightd + offset) >> (log2_denom + 1));
        dst[5] = av_clip_uint8_c((src[5] * weights + dst[5] * weightd + offset) >> (log2_denom + 1));
        dst[6] = av_clip_uint8_c((src[6] * weights + dst[6] * weightd + offset) >> (log2_denom + 1));
        dst[7] = av_clip_uint8_c((src[7] * weights + dst[7] * weightd + offset) >> (log2_denom + 1));
        if(2 == 8) continue;
        dst[8] = av_clip_uint8_c((src[8] * weights + dst[8] * weightd + offset) >> (log2_denom + 1));
        dst[9] = av_clip_uint8_c((src[9] * weights + dst[9] * weightd + offset) >> (log2_denom + 1));
        dst[10] = av_clip_uint8_c((src[10] * weights + dst[10] * weightd + offset) >> (log2_denom + 1));
        dst[11] = av_clip_uint8_c((src[11] * weights + dst[11] * weightd + offset) >> (log2_denom + 1));
        dst[12] = av_clip_uint8_c((src[12] * weights + dst[12] * weightd + offset) >> (log2_denom + 1));
        dst[13] = av_clip_uint8_c((src[13] * weights + dst[13] * weightd + offset) >> (log2_denom + 1));
        dst[14] = av_clip_uint8_c((src[14] * weights + dst[14] * weightd + offset) >> (log2_denom + 1));
        dst[15] = av_clip_uint8_c((src[15] * weights + dst[15] * weightd + offset) >> (log2_denom + 1));
    }
}


static av_always_inline av_flatten void h264_loop_filter_luma_8_c(uint8_t *p_pix, int xstride, int ystride, int inner_iters, int alpha, int beta, int8_t *tc0)
{
    pixel *pix = (pixel *)p_pix;
    int i, d;
    xstride >>= sizeof(pixel) - 1;
    ystride >>= sizeof(pixel) - 1;
    alpha <<= BIT_DEPTH - 8;
    beta  <<= BIT_DEPTH - 8;
    for( i = 0; i < 4; i++ )
    {
        const int tc_orig = tc0[i] << (BIT_DEPTH - 8);
        if( tc_orig < 0 )
        {
            pix += inner_iters * ystride;
            continue;
        }
        for( d = 0; d < inner_iters; d++ )
        {
            const int p0 = pix[-1*xstride];
            const int p1 = pix[-2*xstride];
            const int p2 = pix[-3*xstride];
            const int q0 = pix[0];
            const int q1 = pix[1*xstride];
            const int q2 = pix[2*xstride];

            if( FFABS( p0 - q0 ) < alpha &&
                    FFABS( p1 - p0 ) < beta &&
                    FFABS( q1 - q0 ) < beta )
            {

                int tc = tc_orig;
                int i_delta;

                if( FFABS( p2 - p0 ) < beta )
                {
                    if(tc_orig)
                        pix[-2*xstride] = p1 + av_clip( (( p2 + ( ( p0 + q0 + 1 ) >> 1 ) ) >> 1) - p1, -tc_orig, tc_orig );
                    tc++;
                }
                if( FFABS( q2 - q0 ) < beta )
                {
                    if(tc_orig)
                        pix[   xstride] = q1 + av_clip( (( q2 + ( ( p0 + q0 + 1 ) >> 1 ) ) >> 1) - q1, -tc_orig, tc_orig );
                    tc++;
                }

                i_delta = av_clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
                pix[-xstride] = av_clip_pixel( p0 + i_delta );    /* p0' */
                pix[0]        = av_clip_pixel( q0 - i_delta );    /* q0' */
            }
            pix += ystride;
        }
    }
}
static void h264_v_loop_filter_luma_8_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
{
    h264_loop_filter_luma_8_c(pix, stride, sizeof(uint8_t), 4, alpha, beta, tc0);
}
static void h264_h_loop_filter_luma_8_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
{
    h264_loop_filter_luma_8_c(pix, sizeof(uint8_t), stride, 4, alpha, beta, tc0);
}
static void h264_h_loop_filter_luma_mbaff_8_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
{
    h264_loop_filter_luma_8_c(pix, sizeof(uint8_t), stride, 2, alpha, beta, tc0);
}

static av_always_inline av_flatten void h264_loop_filter_luma_intra_8_c(uint8_t *p_pix, int xstride, int ystride, int inner_iters, int alpha, int beta)
{
    pixel *pix = (pixel *)p_pix;
    int d;
    xstride >>= sizeof(pixel) - 1;
    ystride >>= sizeof(pixel) - 1;
    alpha <<= BIT_DEPTH - 8;
    beta  <<= BIT_DEPTH - 8;
    for( d = 0; d < 4 * inner_iters; d++ )
    {
        const int p2 = pix[-3*xstride];
        const int p1 = pix[-2*xstride];
        const int p0 = pix[-1*xstride];

        const int q0 = pix[ 0*xstride];
        const int q1 = pix[ 1*xstride];
        const int q2 = pix[ 2*xstride];

        if( FFABS( p0 - q0 ) < alpha &&
                FFABS( p1 - p0 ) < beta &&
                FFABS( q1 - q0 ) < beta )
        {

            if(FFABS( p0 - q0 ) < (( alpha >> 2 ) + 2 ))
            {
                if( FFABS( p2 - p0 ) < beta)
                {
                    const int p3 = pix[-4*xstride];
                    /* p0', p1', p2' */
                    pix[-1*xstride] = ( p2 + 2 * p1 + 2 * p0 + 2 * q0 + q1 + 4 ) >> 3;
                    pix[-2*xstride] = ( p2 + p1 + p0 + q0 + 2 ) >> 2;
                    pix[-3*xstride] = ( 2 * p3 + 3 * p2 + p1 + p0 + q0 + 4 ) >> 3;
                }
                else
                {
                    /* p0' */
                    pix[-1*xstride] = ( 2 * p1 + p0 + q1 + 2 ) >> 2;
                }
                if( FFABS( q2 - q0 ) < beta)
                {
                    const int q3 = pix[3*xstride];
                    /* q0', q1', q2' */
                    pix[0*xstride] = ( p1 + 2 * p0 + 2 * q0 + 2 * q1 + q2 + 4 ) >> 3;
                    pix[1*xstride] = ( p0 + q0 + q1 + q2 + 2 ) >> 2;
                    pix[2*xstride] = ( 2 * q3 + 3 * q2 + q1 + q0 + p0 + 4 ) >> 3;
                }
                else
                {
                    /* q0' */
                    pix[0*xstride] = ( 2 * q1 + q0 + p1 + 2 ) >> 2;
                }
            }
            else
            {
                /* p0', q0' */
                pix[-1*xstride] = ( 2 * p1 + p0 + q1 + 2 ) >> 2;
                pix[ 0*xstride] = ( 2 * q1 + q0 + p1 + 2 ) >> 2;
            }
        }
        pix += ystride;
    }
}

static void h264_v_loop_filter_luma_intra_8_c(uint8_t *pix, int stride, int alpha, int beta)
{
    h264_loop_filter_luma_intra_8_c(pix, stride, sizeof(uint8_t), 4, alpha, beta);
}
static void h264_h_loop_filter_luma_intra_8_c(uint8_t *pix, int stride, int alpha, int beta)
{
    h264_loop_filter_luma_intra_8_c(pix, sizeof(uint8_t), stride, 4, alpha, beta);
}
static void h264_h_loop_filter_luma_mbaff_intra_8_c(uint8_t *pix, int stride, int alpha, int beta)
{
    h264_loop_filter_luma_intra_8_c(pix, sizeof(uint8_t), stride, 2, alpha, beta);
}


static av_always_inline av_flatten void h264_loop_filter_chroma_8_c(uint8_t *p_pix, int xstride, int ystride, int inner_iters, int alpha, int beta, int8_t *tc0)
{
    pixel *pix = (pixel *)p_pix;
    int i, d;
    alpha <<= BIT_DEPTH - 8;
    beta  <<= BIT_DEPTH - 8;
    xstride >>= sizeof(pixel) - 1;
    ystride >>= sizeof(pixel) - 1;
    for( i = 0; i < 4; i++ )
    {
        const int tc = ((tc0[i] - 1) << (BIT_DEPTH - 8)) + 1;
        if( tc <= 0 )
        {
            pix += inner_iters * ystride;
            continue;
        }
        for( d = 0; d < inner_iters; d++ )
        {
            const int p0 = pix[-1*xstride];
            const int p1 = pix[-2*xstride];
            const int q0 = pix[0];
            const int q1 = pix[1*xstride];

            if( FFABS( p0 - q0 ) < alpha &&
                    FFABS( p1 - p0 ) < beta &&
                    FFABS( q1 - q0 ) < beta )
            {

                int delta = av_clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );

                pix[-xstride] = av_clip_pixel( p0 + delta );    /* p0' */
                pix[0]        = av_clip_pixel( q0 - delta );    /* q0' */
            }
            pix += ystride;
        }
    }
}
static void h264_v_loop_filter_chroma_8_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
{
    h264_loop_filter_chroma_8_c(pix, stride, sizeof(uint8_t), 2, alpha, beta, tc0);
}
static void h264_h_loop_filter_chroma_8_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
{
    h264_loop_filter_chroma_8_c(pix, sizeof(uint8_t), stride, 2, alpha, beta, tc0);
}
static void h264_h_loop_filter_chroma_mbaff_8_c(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0)
{
    h264_loop_filter_chroma_8_c(pix, sizeof(uint8_t), stride, 1, alpha, beta, tc0);
}


static av_always_inline av_flatten void h264_loop_filter_chroma_intra_8_c(uint8_t *p_pix, int xstride, int ystride, int inner_iters, int alpha, int beta)
{
    pixel *pix = (pixel *)p_pix;
    int d;
    xstride >>= sizeof(pixel) - 1;
    ystride >>= sizeof(pixel) - 1;
    alpha <<= BIT_DEPTH - 8;
    beta  <<= BIT_DEPTH - 8;
    for( d = 0; d < 4 * inner_iters; d++ )
    {
        const int p0 = pix[-1*xstride];
        const int p1 = pix[-2*xstride];
        const int q0 = pix[0];
        const int q1 = pix[1*xstride];

        if( FFABS( p0 - q0 ) < alpha &&
                FFABS( p1 - p0 ) < beta &&
                FFABS( q1 - q0 ) < beta )
        {

            pix[-xstride] = ( 2 * p1 + p0 + q1 + 2 ) >> 2; /* p0' */
            pix[0]        = ( 2 * q1 + q0 + p1 + 2 ) >> 2; /* q0' */
        }
        pix += ystride;
    }
}
static void h264_v_loop_filter_chroma_intra_8_c(uint8_t *pix, int stride, int alpha, int beta)
{
    h264_loop_filter_chroma_intra_8_c(pix, stride, sizeof(uint8_t), 2, alpha, beta);
}
static void h264_h_loop_filter_chroma_intra_8_c(uint8_t *pix, int stride, int alpha, int beta)
{
    h264_loop_filter_chroma_intra_8_c(pix, sizeof(uint8_t), stride, 2, alpha, beta);
}
static void h264_h_loop_filter_chroma_mbaff_intra_8_c(uint8_t *pix, int stride, int alpha, int beta)
{
    h264_loop_filter_chroma_intra_8_c(pix, sizeof(uint8_t), stride, 1, alpha, beta);
}

void ff_h264dsp_init(H264DSPContext *c, const int bit_depth)
{
    c->h264_idct_add = ff_h264_idct_add_8_c;
    c->h264_idct8_add = ff_h264_idct8_add_8_c;
    c->h264_idct_dc_add = ff_h264_idct_dc_add_8_c;
    c->h264_idct8_dc_add = ff_h264_idct8_dc_add_8_c;
    c->h264_idct_add16 = ff_h264_idct_add16_8_c;
    c->h264_idct8_add4 = ff_h264_idct8_add4_8_c;
    c->h264_idct_add8 = ff_h264_idct_add8_8_c;
    c->h264_idct_add16intra = ff_h264_idct_add16intra_8_c;
    c->h264_luma_dc_dequant_idct = ff_h264_luma_dc_dequant_idct_8_c;
    c->h264_chroma_dc_dequant_idct = ff_h264_chroma_dc_dequant_idct_8_c;
    c->weight_h264_pixels_tab[0] = weight_h264_pixels16x16_8_c;
    c->weight_h264_pixels_tab[1] = weight_h264_pixels16x8_8_c;
    c->weight_h264_pixels_tab[2] = weight_h264_pixels8x16_8_c;
    c->weight_h264_pixels_tab[3] = weight_h264_pixels8x8_8_c;
    c->weight_h264_pixels_tab[4] = weight_h264_pixels8x4_8_c;
    c->weight_h264_pixels_tab[5] = weight_h264_pixels4x8_8_c;
    c->weight_h264_pixels_tab[6] = weight_h264_pixels4x4_8_c;
    c->weight_h264_pixels_tab[7] = weight_h264_pixels4x2_8_c;
    c->weight_h264_pixels_tab[8] = weight_h264_pixels2x4_8_c;
    c->weight_h264_pixels_tab[9] = weight_h264_pixels2x2_8_c;
    c->biweight_h264_pixels_tab[0] = biweight_h264_pixels16x16_8_c;
    c->biweight_h264_pixels_tab[1] = biweight_h264_pixels16x8_8_c;
    c->biweight_h264_pixels_tab[2] = biweight_h264_pixels8x16_8_c;
    c->biweight_h264_pixels_tab[3] = biweight_h264_pixels8x8_8_c;
    c->biweight_h264_pixels_tab[4] = biweight_h264_pixels8x4_8_c;
    c->biweight_h264_pixels_tab[5] = biweight_h264_pixels4x8_8_c;
    c->biweight_h264_pixels_tab[6] = biweight_h264_pixels4x4_8_c;
    c->biweight_h264_pixels_tab[7] = biweight_h264_pixels4x2_8_c;
    c->biweight_h264_pixels_tab[8] = biweight_h264_pixels2x4_8_c;
    c->biweight_h264_pixels_tab[9] = biweight_h264_pixels2x2_8_c;
    c->h264_v_loop_filter_luma = h264_v_loop_filter_luma_8_c;
    c->h264_h_loop_filter_luma = h264_h_loop_filter_luma_8_c;
    c->h264_h_loop_filter_luma_mbaff = h264_h_loop_filter_luma_mbaff_8_c;
    c->h264_v_loop_filter_luma_intra = h264_v_loop_filter_luma_intra_8_c;
    c->h264_h_loop_filter_luma_intra = h264_h_loop_filter_luma_intra_8_c;
    c->h264_h_loop_filter_luma_mbaff_intra = h264_h_loop_filter_luma_mbaff_intra_8_c;
    c->h264_v_loop_filter_chroma = h264_v_loop_filter_chroma_8_c;
    c->h264_h_loop_filter_chroma = h264_h_loop_filter_chroma_8_c;
    c->h264_h_loop_filter_chroma_mbaff = h264_h_loop_filter_chroma_mbaff_8_c;
    c->h264_v_loop_filter_chroma_intra = h264_v_loop_filter_chroma_intra_8_c;
    c->h264_h_loop_filter_chroma_intra = h264_h_loop_filter_chroma_intra_8_c;
    c->h264_h_loop_filter_chroma_mbaff_intra = h264_h_loop_filter_chroma_mbaff_intra_8_c;
    c->h264_loop_filter_strength = ((void *)0);;


    //  if (ARCH_ARM) ff_h264dsp_init_arm(c, bit_depth);
    //   if (HAVE_ALTIVEC) ff_h264dsp_init_ppc(c, bit_depth);
    //   if (HAVE_MMX) ff_h264dsp_init_x86(c, bit_depth);
}
